#include "ChatWidget.h"

ChatWidget::ChatWidget(QWidget *parent) :
    QWidget(parent) {
    createWidgets();
    createLayouts();
    connectSignalSlots();

    initializeHash();
}

void ChatWidget::newConnection() {
    chatLog->append(QString("<div class=\"notice\">Connected to opponent</div>"), Chat::NONE);
}

void ChatWidget::newGame() {
    chatLog->append(QString("<div class=\"notice\">New game started</div>"), Chat::NONE);
}

void ChatWidget::socketMessage(Network::SocketMessage message) {
    QString messageString;
    switch (message) {
    case Network::REQUEST_NEW_GAME:
        messageString = "<div class=\"request\">Received a request for a new game: <a href=\"accept_new_game\">Accept</a> or <a href=\"reject_new_game\">Reject</a></div>";
        break;
    case Network::ACCEPT_NEW_GAME:
        messageString = "<div class=\"accept\">Request for new game accepted</div>";
        break;
    case Network::REJECT_NEW_GAME:
        messageString = "<div class=\"reject\">Request for new game rejected</div>";
        break;
    case Network::REQUEST_UNDO:
        messageString = "<div class=\"request\">Received a request for an undo: <a href=\"accept_undo\">Accept</a> or <a href=\"reject_undo\">Reject</a></div>";
        break;
    case Network::ACCEPT_UNDO:
        messageString = "<div class=\"accept\">Request for undo accepted</div>";
        break;
    case Network::REJECT_UNDO:
        messageString = "<div class=\"reject\">Request for undo rejected</div>";
        break;
    default:
        return;
        break;
    }
    chatLog->append(messageString, Chat::NONE);
}

void ChatWidget::userRequest(Network::SocketMessage message) {
    QString messageString;
    switch (message) {
    case Network::REQUEST_NEW_GAME:
        messageString = "<div class=\"request\">Requesting a new game...</div>";
        break;
    case Network::REQUEST_UNDO:
        messageString = "<div class=\"request\">Requesting an undo...</div>";
        break;
    default:
        return;
        break;
    }
    chatLog->append(messageString, Chat::NONE);
}

void ChatWidget::chatMessage(QString chat) {
    chatLog->append(chat, Chat::OPPONENT_CHAT);
}

void ChatWidget::confirmRespond(Network::SocketMessage message) {
    QString messageString;
    switch (message) {
    case Network::ACCEPT_NEW_GAME:
        messageString = "<div class=\"accept\">Accepted request for new game</div>";
        break;
    case Network::REJECT_NEW_GAME:
        messageString = "<div class=\"reject\">Rejected request for a new game</div>";
        break;
    case Network::ACCEPT_UNDO:
        messageString = "<div class=\"accept\">Accepted request for an undo</div>";
        break;
    case Network::REJECT_UNDO:
        messageString = "<div class=\"reject\">Rejected request for an undo</div>";
        break;
    default:
        return;
        break;
    }
    chatLog->append(messageString, Chat::NONE);
}

void ChatWidget::playerWon(bool player) {
    QString messageString;
    if (player) {
        messageString = "<div class=\"notice\">You won!</div>";
    } else {
        messageString = "<div class=\"notice\">You lost</div>";
    }
    chatLog->append(messageString, Chat::NONE);
}

void ChatWidget::changeConnectionStatus(Network::ConnectionStatus status) {

}

void ChatWidget::socketError(QAbstractSocket::SocketError error) {

}

void ChatWidget::socketDisconnected() {
    chatLog->append(QString("<div class=\"urgent\">Disconnected from opponent</div>"), Chat::NONE);
}

bool ChatWidget::eventFilter(QObject * object, QEvent * event) {
    if (object == chatInput) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
            switch (keyEvent->key()) {
            case Qt::Key_Return:
            case Qt::Key_Enter:
                chatSubmit();
            case Qt::Key_Less:
            case Qt::Key_Greater:
                return true;
                break;
            default:
                return false;
            }
        } else {
            return false;
        }
    } else {
        return QWidget::eventFilter(object, event);
    }
}

void ChatWidget::linkOnClick(const QUrl & link) {
    emit responseSubmitted((Network::SocketMessage) linkMessageMap[link.toString()]);
}

void ChatWidget::createWidgets() {
    chatLog = new ChatLogWidget();
    chatLog->setAlignment(Qt::AlignLeft);
    chatLog->setOpenLinks(false);
    chatLog->setReadOnly(true);
    chatLog->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    chatInput = new QPlainTextEdit();
    chatInput->setFixedHeight(QFontMetrics(chatInput->font()).lineSpacing() * CHAT_ROWS);
    chatInput->installEventFilter(this);
}

void ChatWidget::createLayouts() {
    QVBoxLayout * mainLayout = new QVBoxLayout;
    mainLayout->addWidget(chatLog);
    mainLayout->addWidget(chatInput);
    mainLayout->setMargin(MARGINS);
    mainLayout->setAlignment(Qt::AlignCenter);
    setLayout(mainLayout);
}

void ChatWidget::connectSignalSlots() {
    connect(chatLog, SIGNAL(anchorClicked(QUrl)), this, SLOT(linkOnClick(QUrl)));
}

void ChatWidget::initializeHash() {
    linkMessageMap["accept_new_game"] = Network::ACCEPT_NEW_GAME;
    linkMessageMap["reject_new_game"] = Network::REJECT_NEW_GAME;
    linkMessageMap["accept_undo"] = Network::ACCEPT_UNDO;
    linkMessageMap["reject_undo"] = Network::REJECT_UNDO;
}

void ChatWidget::chatSubmit() {
    QString chat = chatInput->toPlainText();
    if (!chat.isEmpty()) {
        emit chatSubmitted(chat);
        chatLog->append(chat, Chat::PLAYER_CHAT);
        chatInput->clear();
    }
}
